/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.videodes.impl;

import com.thoughtworks.xstream.XStream;
import cz.muni.fi.pb138.videodes.api.base.XMLDBTemplate;
import cz.muni.fi.pb138.videodes.api.base.RowMapper;
import cz.muni.fi.pb138.videodes.entity.Genre;
import cz.muni.fi.pb138.videodes.entity.Movie;
import java.util.List;

/**
 *
 * @author pseudo
 */
public class MovieManagerImpl implements MovieManager {

    @Override
    public void add(Movie movie) {
        if (movie == null) {
            throw new IllegalArgumentException("the parameter item cannot be null");
        }
        if (movie.getId() != null) {
            throw new IllegalArgumentException("the id of the given parameter cannot be set");
        }

        XStream x = new XStream();
        x.omitField(Movie.class, "id");
        x.alias("movie", Movie.class);
        x.alias("actor", String.class);
        x.alias("genre", Genre.class);

        String xml = x.toXML(movie);

        if (!XMLValidation.validate(xml, "cz/muni/fi/pb138/videodes/files/movieSchema.xsd")) {
            return;
        }
        
        String id = XMLDBTemplate.storeResource("/movie", xml);
        movie.setId(id);
    }

    @Override
    public void remove(Movie movie) {
        if (movie == null) {
            throw new IllegalArgumentException("the parameter item cannot be null");
        }
        if (movie.getId() == null) {
            throw new IllegalArgumentException("the id of the given parameter must be set");
        }
        
        String xquery = "for $movieToDelete in collection('/db/dvd')//movie[@id = '?'] "
                + "return update delete $movieToDelete";

        XMLDBTemplate.removeResource("/movie", movie.getId());
        XMLDBTemplate.executeQuery(xquery, movie.getId());
    }

    @Override
    public void update(Movie movie) {
        if (movie == null) {
            throw new IllegalArgumentException("the parameter item cannot be null");
        }
        if (movie.getId() == null) {
            throw new IllegalArgumentException("the id of the given parameter must be set");
        }

        XStream x = new XStream();
        x.omitField(Movie.class, "id");
        x.alias("movie", Movie.class);
        x.alias("actor", String.class);
        x.alias("genre", Genre.class);

        String xml = x.toXML(movie);
        
        if (!XMLValidation.validate(xml, "cz/muni/fi/pb138/videodes/files/movieSchema.xsd")) {
            return;
        }

        XMLDBTemplate.updateResource("/movie", xml, movie.getId());
    }

    @Override
    public List<Movie> getAllMovies() {
        RowMapper<Movie> rowMapper = new MovieRowMapper();

        String xquery = "for $movie in collection('/db/movie')//movie "
                + "return $movie";

        List<Movie> movies = XMLDBTemplate.executeQueryAsList(xquery, rowMapper);

        return movies;
    }

    @Override
    public Movie getMovieById(String id) {
        RowMapper<Movie> rowMapper = new MovieRowMapper();

        String xquery = "doc('/db/movie/?')/movie";

        Movie movie = XMLDBTemplate.executeQueryAsValue(xquery, rowMapper, id);
        if (movie == null) {
            throw new IllegalArgumentException("No element with an expected id retrieved from the database");
        }

        return movie;
    }

    @Override
    public List<Movie> getMoviesByGenre(Genre genre) {
        RowMapper<Movie> rowMapper = new MovieRowMapper();

        String xquery = "for $movie in collection('/db/movie')//movie "
                + "where $movie/genres/*[contains(., \"?\")]"
                + "return $movie";

        List<Movie> movies = XMLDBTemplate.executeQueryAsList(xquery, rowMapper, genre.toString());

        return movies;
    }
}
